cmake_minimum_required(VERSION 3.16)
project(tt_proto LANGUAGES CXX)

set(MINGW32_ROOT "C:/Qt/5.15.2/mingw81_32")
set(GRPC_ROOT "C:/Program Files (x86)/grpc")
set(CMAKE_PREFIX_PATH "${MINGW32_ROOT}" "${GRPC_ROOT}/lib/cmake")
set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/install)

set(CMAKE_POSITION_INDEPENDENT_CODE ON)
find_package(protobuf CONFIG REQUIRED)
find_package(gRPC CONFIG REQUIRED)
find_package(Threads REQUIRED)

find_program(EXEC_PROTOC
    NAMES protoc.exe
    PATHS ${GRPC_ROOT}/bin
    NO_SYSTEM_ENVIRONMENT_PATH
)

find_program(EXEC_GRPC_CPP_PLUGIN
    NAMES grpc_cpp_plugin.exe
    PATHS ${GRPC_ROOT}/bin
    NO_SYSTEM_ENVIRONMENT_PATH
)

message(STATUS "EXEC_PROTOC: ${EXEC_PROTOC}")
message(STATUS "EXEC_GRPC_CPP_PLUGIN: ${EXEC_GRPC_CPP_PLUGIN}")

include_directories(
    ${CMAKE_CURRENT_SOURCE_DIR}
    ${CMAKE_BINARY_DIR}/generated
    ${GRPC_ROOT}/include
)

file(GLOB_RECURSE PROTO_FILES "*.proto")

# List to collect all generated files
set(ALL_GENERATED_FILES)

foreach(PROTO_FILE ${PROTO_FILES})
    # Get relative path from source directory to maintain directory structure
    file(RELATIVE_PATH PROTO_REL_PATH ${CMAKE_CURRENT_SOURCE_DIR} ${PROTO_FILE})
    get_filename_component(PROTO_REL_DIR ${PROTO_REL_PATH} DIRECTORY)
    get_filename_component(PROTO_NAME ${PROTO_FILE} NAME_WE)
    
    set(GRPC_OUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated")
    set(PROTO_OUT_DIR "${GRPC_OUT_DIR}/${PROTO_REL_DIR}")
    
    set(PROTO_SRC "${PROTO_OUT_DIR}/${PROTO_NAME}.pb.cc")
    set(PROTO_HEADER "${PROTO_OUT_DIR}/${PROTO_NAME}.pb.h")
    set(GRPC_SRC "${PROTO_OUT_DIR}/${PROTO_NAME}.grpc.pb.cc")
    set(GRPC_HEADER "${PROTO_OUT_DIR}/${PROTO_NAME}.grpc.pb.h")

    add_custom_command(
        OUTPUT ${PROTO_SRC} ${PROTO_HEADER} ${GRPC_SRC} ${GRPC_HEADER}
        COMMAND ${CMAKE_COMMAND} -E make_directory ${PROTO_OUT_DIR}
        COMMAND ${EXEC_PROTOC}
        ARGS --proto_path=${CMAKE_CURRENT_SOURCE_DIR} --experimental_allow_proto3_optional --cpp_out=${GRPC_OUT_DIR} --grpc_out=${GRPC_OUT_DIR} --plugin=protoc-gen-grpc=${EXEC_GRPC_CPP_PLUGIN} ${PROTO_FILE}
        DEPENDS ${PROTO_FILE}
        COMMENT "Generating C++ code from ${PROTO_REL_PATH}"
    )
    
    # Add generated files to the list
    list(APPEND ALL_GENERATED_FILES ${PROTO_SRC} ${PROTO_HEADER} ${GRPC_SRC} ${GRPC_HEADER})
endforeach()

# Create a custom target that depends on all generated files
add_custom_target(generate_proto_code ALL DEPENDS ${ALL_GENERATED_FILES})

file(GLOB_RECURSE SRC_FILES "${CMAKE_BINARY_DIR}/generated/*.cc")
add_definitions(
    -DNOMINMAX              # 避免 Windows.h 中的 min/max 宏冲突
    -D_WIN32_WINNT=0x0601   # 支持 Windows 7 及以上
)


add_library(${PROJECT_NAME} STATIC ${ALL_GENERATED_FILES})
target_link_libraries(${PROJECT_NAME}
    protobuf::libprotobuf
    gRPC::grpc++
    Threads::Threads
)

install(TARGETS ${PROJECT_NAME} DESTINATION lib)

install(DIRECTORY ${CMAKE_BINARY_DIR}/generated/
    DESTINATION include
    FILES_MATCHING PATTERN "*.h"
)